#!/bin/sh
# Check repository for outdated packages

die() {
    printf '%s\n' "$*" >&2
    exit 1
}

mkcd() {
    mkdir -p "$1" && cd "$1"
}

repology_name() {
    # Fix any known naming inconsistences between packages and Repology.
    remote=$(
        # Strip unrelated suffixes.
        remote=${1%%-bin}
        remote=${remote%%-git}

        # Remote names are all lowercase.
        tr '[:upper:]' '[:lower:]' <<EOF |
$remote
EOF
        # Remote always uses -.
        tr _ -
    )

    case $remote in
        baseinit|baselayout|kiss)
            remote=-
        ;;

        clang)
            remote=llvm
        ;;

        dash)
            remote=dash-shell
        ;;

        dejavu-ttf)
            remote=fonts:dejavu
        ;;

        dsp)
            remote=dsp-audio-processing
        ;;

        emacs-nox)
            # TODO [community]: Make default emacs no x11?
            remote=emacs
        ;;

        fd)
            remote=fd-find
        ;;

        fetsh)
            # TODO [community]: Rename package?
            remote=fet.sh
        ;;

        firefox-esr)
            remote=firefox
        ;;

        font-awesome-ttf)
            remote=fonts:fontawesome
        ;;

        foot-pgo)
            remote=foot
        ;;

        gc)
            remote=boehm-gc
        ;;

        gnugrep)
            # shell-check is dumb here so this must be quoted.
            remote='grep'
        ;;

        gnupg[12])
            # Reported to repology.org.
            # https://github.com/repology/repology-rules/issues/285
            remote=gnupg
        ;;

        gtk+3)
            remote=gtk3+classic
        ;;

        gst-*)
            remote=gstreamer:${remote##*-}
        ;;

        gtar)
            remote=tar
        ;;

        eiwd)
            remote=iwd
        ;;

        hack)
            # It might be nice to adopt Repology's naming scheme for
            # fonts as it also makes them self-documenting and easy
            # to search for ('kiss s font:\*).
            remote=fonts:hack
        ;;

        harfbuzz-icu)
            # TODO: Report to repology.org?
            # Package split.
            remote=harfbuzz
        ;;

        libelf)
            remote=elfutils
        ;;

        liberation-fonts)
            remote=fonts:liberation
        ;;

        libmupdf | libxaw3d)
            # TODO [community]: Rename packages?
            remote=${remote##lib}
        ;;

        libseat)
            remote=seatd
        ;;

        links2)
            # TODO [community]: Rename package?
            remote=links
        ;;

        linux-headers)
            remote=linux
        ;;

        lux)
            remote=lux-brightness-ventto
        ;;

        man-pages)
            # TODO: Report to repology.org.
            # man-pages       -> manpages
            # man-pages-posix -> man-pages-posix
            remote=manpages
        ;;

        netsurf-fb)
            remote=netsurf
        ;;

        openjpeg2)
            # TODO [community]: Rename package?
            remote=openjpeg
        ;;

        osh)
            remote=oil-shell
        ;;

        pinentry-dmenu)
            remote=pinentry-dmenu-cemkeylan
        ;;

        pyqt5)
            # TODO [community]: Rename package?
            remote=python-qt
        ;;

        python2)
            remote=python
        ;;

        qt5*)
            remote=qt
        ;;

        rage)
            remote=rage-encryption-tool
        ;;

        sane)
            remote=sane-backends
        ;;

        spleen-font)
            remote=fonts:spleen
        ;;

        sshfs)
            remote=fusefs:sshfs
        ;;

        surf)
            remote=surf-browser
        ;;

        st)
            remote=st-term
        ;;

        sway-no-seat | sway-tiny)
            remote=sway
        ;;

        terminus-font)
            remote=fonts:terminus
        ;;

        tiv)
            remote=tiv-unclassified
        ;;

        unifont)
            remote=fonts:unifont
        ;;

        webkit2gtk)
            # TODO [community]: Rename package?
            remote=webkitgtk
        ;;

        xf86-*)
            remote=xdrv:${remote##*-}
        ;;

        xmlsec1)
            # TODO [community]: Rename package?
            remote=xmlsec
        ;;
    esac
}

repology_version() {
    [ -f "$1.svg" ] || return 1
    read -r remote_ver < "$1.svg" || :
    remote_ver=${remote_ver%</text>*}
    remote_ver=${remote_ver##*>}
}

repo_version() {
    read -r ver _ 2>/dev/null < "$2/version" || {
        printf '%-30s local version not found\n' "$1" >&2
        return 1
    }

    [ "$ver" != git ]
}

get_outdated() {
    repo=${repo%%/}
    printf '\n[Checking Repology for outdated packages in %s]\n\n' "$repo" >&2

    for pkg in */; do
        pkg=${pkg%%/}
        repology_name "${pkg##*/}"

        [ "$remote" = - ] ||
            set -- "$@" -z "$remote.svg" \
                "https://repology.org/badge/latest-versions/$remote.svg"
    done

    mkcd "$tmp/${repo##*/}"

    curl -SsZ --parallel-max 16 --remote-name-all "$@" ||
        die 'fatal: network error'

    for _pkg in "$OLDPWD"/*/; do
        pkg=${_pkg%%/}
        pkg=${pkg##*/}

        repo_version  "$pkg" "$_pkg" || continue
        repology_name "$pkg"
        repology_version "$remote" || continue

        case $remote_ver in *", $ver"* | *"$ver,"* | "$ver" | - | '')
            continue
        esac

        printf '%-30s %s -> %s\n' "$pkg" "$ver" "$remote_ver"
    done
}

main() {
    set -e

    [ "$1" ] ||
        die 'usage: kiss [ou]tdated /path/to/repo...'

    mkdir -p "${tmp:=${XDG_CACHE_HOME:-"$HOME/.cache"}/kiss/repology}"

    for repo do
        old_pwd=$PWD
        cd "$repo"
        get_outdated
        cd "$old_pwd"
    done
}

main "$@"
